import React from 'react';
import calendarJs from '../../../../components/calendarJs/calendarJs';
import { Carousel, DatePicker, Toast, Badge, Modal } from 'antd-mobile';
import * as config from '../../../../components/config/config';
import * as utils from '../../../../components/utils/utils';
import Loading from '../../../../components/loading/loading';
import ajax from '../../../../components/ajax/ajax';
import './signinCalendar.css';

class SigninCalendar extends React.Component {
    constructor (props) {
        super(props);

        const initialCalendar = this.getInitialCalendar();

        this.state = {
            calendarList: initialCalendar.calendarList,
            monthTitleList: initialCalendar.monthTitleList,
            activeSlideIndex: initialCalendar.calendarList.length - 1,
            constellation: {
                name: '',
                fortune: [],
                bad_good: {
                    bad: [],
                    good: []
                },
                question: {
                    content: '',
                    options: [{ count: 0, name: '', voted: false }, { count: 0, name: '', voted: false }]
                }
            },
            signinCardCount: 0,
            willUseSigninCardCount: 0,
            signinCardPopVisible: false
        };

        this.storage = {
            monthPickerValue: new Date(),
            constellationAvatarClassNamelMap: {
                '摩羯座': 'constellation-name-1',
                '水瓶座': 'constellation-name-2',
                '双鱼座': 'constellation-name-3',
                '白羊座': 'constellation-name-4',
                '金牛座': 'constellation-name-5',
                '双子座': 'constellation-name-6',
                '巨蟹座': 'constellation-name-7',
                '狮子座': 'constellation-name-8',
                '处女座': 'constellation-name-9',
                '天秤座': 'constellation-name-10',
                '天蝎座': 'constellation-name-11',
                '射手座': 'constellation-name-12'
            },
            userToken: '',
            loadedSignRecordDateList: [],
            signinDateListUseCard: []
        };
    }

    componentDidMount () {
        // 解决antd-mobile 走马灯 item高度不一致时，高度较大的显示不完整的bug
        const lastCalendarSlide = document.querySelector('.calendar .slider-slide:last-child');
        if (lastCalendarSlide) { lastCalendarSlide.classList.add('active'); }
    }

    UNSAFE_componentWillReceiveProps (props) {
        if (props.today) {
            const year = calendarJs.getYear(props.today);
            const month = calendarJs.getMonth(props.today);
            const day = calendarJs.getDay(props.today);
            this.updateCalendarDayObjProperty(year, month, day, 'day', '今');
            this.updateCalendarDayObjProperty(year, month, day, 'isToday', true);
            this.updateCalendarDayObjProperty(year, month, day, 'isSigned', true);
        }
        if (props.userToken && !this.storage.userToken) {
            this.storage.userToken = props.userToken;
            // 获取补签卡数量
            this.getwalletInfo();
            // 获取运势信息
            this.getConstellationData();
            // 获取当月签到记录
            this.getMonthSignRecord(calendarJs.getYear(), calendarJs.getMonth());
        }
    }

    getwalletInfo () {
        const loading = Loading.show('加载中...');
        ajax.get({
            url: `${config.HOST_MONEY}${config.XHR_REQ_URL.WALLET_INFO}`,
            header: { Qbtoken: this.storage.userToken }
        }).then((res) => {
            loading.hide();

            if (res.err === config.XHR_RES_CODE.SUCCESS) {
                this.setState({
                    signinCardCount: res.sign_left
                });
            }
            else {
                throw new Error(res.err_msg);
            }
        }).catch((err) => {
            loading.hide();
            Toast.info(err.message || '网络错误');
        });
    }

    // 修改原始日历数据结构，便于展示
    getInitialCalendar () {
        const monthTitleList = [];
        const calendarList = [];
        const calendarData = calendarJs.getCalendar('2015/9/1');
        Object.keys(calendarData).forEach((year) => {
            Object.keys(calendarData[year]).forEach((month) => {
                monthTitleList.push({
                    text: `${year}年${month}月`,
                    year: year,
                    month: month
                });
                calendarList.push(calendarData[year][month]);
            });
        });

        return {
            calendarList: calendarList,
            monthTitleList: monthTitleList
        };
    }

    // 获取星座运势相关的数据
    getConstellationData () {
        const loading = Loading.show('加载中...');
        ajax.get({
            url: `${config.HOST_CIRCLE}${config.XHR_REQ_URL.FORTUNE_LIST}`,
            header: { Qbtoken: this.storage.userToken }
        }).then((res) => {
            loading.hide();

            if (res.err === config.XHR_RES_CODE.SUCCESS) {
                this.setState({
                    constellation: {
                        name: res.astrology,
                        fortune: res.fortune,
                        bad_good: {
                            bad: res.yj.avoid || [],
                            good: res.yj.fit || []
                        },
                        question: {
                            content: res.title,
                            options: res.options
                        }
                    }
                });
            }
            else {
                throw new Error(res.err_msg);
            }
        }).catch((err) => {
            loading.hide();
            Toast.info(err.message || '网络错误');
        });
    }

    getMonthSignRecord (year, month) {
        // 判断 year年month月的签到数据是否已经加载过，如果加载过直接return
        const hasLoaded = this.storage.loadedSignRecordDateList.find((item) => {
            return ('' + item.year) === ('' + year) && ('' + item.month) === ('' + month);
        });

        if (hasLoaded) { return; }

        const loading = Loading.show('加载中...');
        ajax.get({
            url: `${config.HOST_CIRCLE}${config.XHR_REQ_URL.SIGN_MONTH_RECORD}`,
            header: { Qbtoken: this.storage.userToken },
            params: {
                date: `${year}-${month}`
            }
        }).then((res) => {
            loading.hide();

            if (res.err === config.XHR_RES_CODE.SUCCESS) {
                // 缓存已经加载过签到记录的年与月
                this.storage.loadedSignRecordDateList.push({
                    year: year,
                    month: month
                });
                this.updateCalendarListSignState(year, month, res.signs);
            }
            else {
                throw new Error(res.err_msg);
            }
        }).catch((err) => {
            loading.hide();
            Toast.info(err.message || '获取本月签到记录失败');
        });
    }

    updateCalendarListSignState (year, month, signs) {
        const calendarList = this.state.calendarList;
        const currMonthCalendarIndex = this.state.monthTitleList.findIndex((item) => {
            return ('' + item.year) === ('' + year) && ('' + item.month) === ('' + month);
        });
        const currMonthCalendar = calendarList[currMonthCalendarIndex];

        for (let i = 0; i < signs.length; i++) {
            const sign = signs[i].split('-');
            const sign_day = parseInt(sign[2]);

            for (let j = 0; j < currMonthCalendar.length; j++) {
                const week = currMonthCalendar[j];
                const dayObj = week.find((item) => {
                    return item.fullDate && ('' + sign_day) === ('' + item.fullDate.day);
                });

                if (dayObj) {
                    dayObj.isSigned = true;
                    break;
                }
            }
        }

        this.setState({
            calendarList: calendarList
        });
    }

    renderCalendarPanel () {
        return this.state.calendarList.map((weeks, index) => {
            const weekTitleList = ['周一', '周二', '周三', '周四', '周五', '周六', '周日'];

            return (
                <div key={index} className="panel" onClick={(e) => { this.handleCalendarClick(e); }}>
                    <ul className="weekTitle row">
                        {
                            weekTitleList.map((title, titleIndex) => {
                                return <li className="cell" key={`weekTitle${index}${titleIndex}`}>{title}</li>;
                            })
                        }
                    </ul>
                    {
                        weeks.map((week, weekIndex) => <ul key={`${index}${weekIndex}`} className="week row">
                            {
                                week.map((dayObj, dayIndex) => {
                                    return (
                                        <li
                                            key={`${index}${weekIndex}${dayIndex}`}
                                            className={`day cell ${dayObj.isSigned ? 'signed' : ''} ${dayObj.isWaitSign ? 'waitSign' : ''} ${dayObj.isToday ? 'today' : ''}`}
                                            fulldate={JSON.stringify(dayObj.fullDate)}
                                        >
                                            {dayObj.day}
                                        </li>
                                    );
                                })
                            }
                        </ul>)
                    }
                </div>
            );
        });
    }

    renderConstellation () {
        const constellationData = this.state.constellation;
        const questionOptions = constellationData.question.options;

        return (
            <div className="constellation">
                <div className="title">
                    <p><i className={`icon ${this.storage.constellationAvatarClassNamelMap[constellationData.name]}`}></i></p>
                    <p><span className="name">{constellationData.name}</span></p>
                </div>
                <ul className="fortune">
                    {
                        constellationData.fortune.filter((item) => {
                            return ('' + item.type) === '2';
                        }).map((item) => {
                            return (
                                <li key={item.name}>
                                    <span className="title">{item.name}</span>
                                    <span className={`value-icon value-icon-${item.value}`}>
                                        <i></i><i></i><i></i><i></i><i></i>
                                    </span>
                                </li>
                            );
                        })
                    }
                </ul>
                <ul className="fortune">
                    {
                        constellationData.fortune.filter((item) => {
                            return ('' + item.type) === '1';
                        }).map((item) => {
                            return (
                                <li key={item.name}>
                                    <span className="title">{item.name}:</span>
                                    <span className="value-text">{item.value}</span>
                                </li>
                            );
                        })
                    }
                </ul>
                <div className="question">
                    <p className="content">{constellationData.question.content}</p>
                    <div className="answer">
                        <div
                            className={`option ${questionOptions[0].voted ? 'selected' : ''}`}
                            onClick={() => { this.handleAnswerOptionClick(questionOptions[0].name, 0); }}
                        >
                            {`${questionOptions[0].name} ${questionOptions[0].count}`}
                        </div>
                        <div className="vs"></div>
                        <div
                            className={`option ${questionOptions[1].voted ? 'selected' : ''}`}
                            onClick={() => { this.handleAnswerOptionClick(questionOptions[1].name, 1); }}
                        >
                            {`${questionOptions[1].name} ${questionOptions[1].count}`}
                        </div>
                    </div>
                </div>
            </div>
        );
    }

    renderMonthTitle () {
        return (
            <DatePicker
                mode="month"
                minDate={new Date(2015, 9, 1, 0, 0, 0)}
                maxDate={new Date()}
                value={this.storage.monthPickerValue}
                onOk={(value) => { this.handleMonthPickerConfirm(value); }}
            >
                <div className="monthTitle">
                    <div className="listWrapper">
                        <ul className="list" style={{ top: `-${this.state.activeSlideIndex * 100}%` }}>
                            {
                                this.state.monthTitleList.map((item, index) => {
                                    return (
                                        <li
                                            key={item.text}
                                            className={index === this.state.activeSlideIndex ? 'active' : ''}
                                        >{item.text}</li>);
                                })
                            }
                        </ul>
                    </div>
                    <i className="icon"></i>
                </div>
            </DatePicker>
        );
    }

    renderSigninCardPop () {
        return (
            <div className={`signinCardPop ${this.state.signinCardPopVisible ? 'show' : ''}`}>
                <div className="row tip">
                    <div className="col">补签：<strong>{this.state.willUseSigninCardCount}</strong>天</div>
                    <div className="col">{`还可补签${this.state.signinCardCount - this.state.willUseSigninCardCount}天`}</div>
                </div>
                <div className="btn-useSigninCard" onClick={() => { this.handleUseSigninCardClick(); }}>确认补签</div>
            </div>
        );
    }

    handleUseSigninCardClick () {
        const loading = Loading.show();
        ajax.post({
            url: `${config.HOST_CIRCLE}${config.XHR_REQ_URL.SIGNIN_CONTINUE_DAYS_AFTER_USE_CARD}`,
            header: { Qbtoken: this.storage.userToken },
            params: {
                days: this.storage.signinDateListUseCard
            }
        }).then((res) => {
            loading.hide();

            if (res.err === config.XHR_RES_CODE.SUCCESS) {
                const alertCont = <div>
                    <p>确定使用{this.state.willUseSigninCardCount}张补签卡</p>
                    <p>补签后，连续签到达到{res.count}天</p>
                </div>;
                Modal.alert('', alertCont, [
                    { text: '取消' },
                    { text: '确定补签', onPress: () => { this.signinUseCard(); } }
                ]);
            }
            else {
                throw new Error(res.err_msg);
            }
        }).catch((err) => {
            loading.hide();
            Toast.info(err.message || '网络错误');
        });
    }

    signinUseCard () {
        const loading = Loading.show();
        ajax.post({
            url: `${config.HOST_CIRCLE}${config.XHR_REQ_URL.SIGNIN_USE_CARD}`,
            header: { Qbtoken: this.storage.userToken },
            params: {
                days: this.storage.signinDateListUseCard.map((date) => {
                    return calendarJs.getDateString(date, true, '-');
                })
            }
        }).then((res) => {
            loading.hide();

            if (res.err === config.XHR_RES_CODE.SUCCESS) {
                this.setState((preState) => {
                    return {
                        signinCardCount: preState.signinCardCount - preState.willUseSigninCardCount,
                        willUseSigninCardCount: 0,
                        signinCardPopVisible: false
                    };
                });
                Toast.info(`补签成功，已连续签到${res.days}，补签卡剩余${this.state.signinCardCount - this.state.willUseSigninCardCount}张`);
                this.storage.signinDateListUseCard.forEach((item) => {
                    const year = calendarJs.getYear(item);
                    const month = calendarJs.getMonth(item);
                    const day = calendarJs.getDay(item);
                    this.updateCalendarDayObjProperty(year, month, day, 'isWaitSign', false);
                    this.updateCalendarDayObjProperty(year, month, day, 'isSigned', true);
                });
                this.storage.signinDateListUseCard = [];
            }
            else {
                throw new Error(res.err_msg);
            }
        }).catch((err) => {
            loading.hide();
            Toast.info(err.message || '网络错误');
        });
    }

    handleTodayJumpClick () {
        this.setState((preState) => {
            return {
                activeSlideIndex: preState.calendarList.length - 1
            };
        });
    }

    handleAnswerOptionClick (name, index) {
        const isVoted = this.state.constellation.question.options.find((item) => {
            return item.voted;
        });

        if (isVoted) { return; }

        const loading = Loading.show('投票中...');
        ajax.post({
            url: `${config.HOST_CIRCLE}${config.XHR_REQ_URL.FORTUNE_VOTE}`,
            header: { Qbtoken: this.storage.userToken },
            params: {
                option: name
            }
        }).then((res) => {
            loading.hide();

            if (res.err === config.XHR_RES_CODE.SUCCESS) {
                const constellationData = this.state.constellation;
                const votedItem = constellationData.question.options.find((item) => {
                    return item.name === name;
                });

                votedItem.voted = true;
                votedItem.count = votedItem.count + 1;

                this.setState({
                    constellation: constellationData
                });
            }
            else {
                throw new Error(res.err_msg);
            }
        }).catch((err) => {
            loading.hide();
            Toast.info(err.message || '投票失败');
        });
    }

    handleMonthPickerConfirm (date) {
        const year = calendarJs.getYear(date);
        const month = calendarJs.getMonth(date);

        this.setState((preState) => {
            return {
                activeSlideIndex: preState.monthTitleList.findIndex((item) => {
                    if (('' + item.year) === ('' + year) && ('' + item.month) === ('' + month)) {
                        this.storage.monthPickerValue = new Date(item.year, item.month, 1, 0, 0, 0);
                        return true;
                    }
                    return false;
                })
            };
        });
    }

    handleCalendarClick (event) {
        const start = Date.now();
        const classNameList = event.target.classList;
        const fullDateAttr = event.target.getAttribute('fulldate');
        const fulldate = JSON.parse(fullDateAttr);
        const isClickedDayCell = classNameList.contains('day') && classNameList.contains('cell');
        const isUnsignDay = !classNameList.contains('signed');
        const isWaitSignDay = classNameList.contains('waitSign');
        const nowDate = new Date(calendarJs.getYear(), calendarJs.getMonth(), calendarJs.getDay());
        const clickedDate = new Date(fulldate.year, fulldate.month, fulldate.day);
        const isBeforeDay = clickedDate <= nowDate;

        if (isClickedDayCell && fullDateAttr && isBeforeDay) {
            if (isUnsignDay) {
                const hasExtraCard = this.state.signinCardCount > 0 && (this.state.willUseSigninCardCount + 1) <= this.state.signinCardCount;
                if (isWaitSignDay || hasExtraCard) {
                    let isWaitSign = !!this.getCalendarDayObjProperty(fulldate.year, fulldate.month, fulldate.day, 'isWaitSign');
                    isWaitSign = !isWaitSign;

                    this.updateCalendarDayObjProperty(fulldate.year, fulldate.month, fulldate.day, 'isWaitSign', isWaitSign, () => {
                        // 补签pop显隐
                        // 补签次数文案修改
                        const canShowSigninCardPop = document.querySelectorAll('.day.cell.waitSign').length > 0;

                        this.setState((preState) => {
                            return {
                                signinCardPopVisible: canShowSigninCardPop,
                                willUseSigninCardCount: preState.willUseSigninCardCount + (isWaitSign ? 1 : -1)
                            };
                        });

                        if (isWaitSign) {
                            utils.addArrayItem(this.storage.signinDateListUseCard, `${fulldate.year}-${fulldate.month}-${fulldate.day}`);
                        }
                        else {
                            utils.deleteArrayItem(this.storage.signinDateListUseCard, (item, index) => {
                                return item === `${fulldate.year}-${fulldate.month}-${fulldate.day}`;
                            });
                        }
                    });
                }
                else {
                    // 引导购买补签卡
                    this.alertBuySigninCardModal();
                }
            }
            else {
                Toast.info('这天你已经签到过咯，点击空白日期补签~');
            }
        }
        else {
            return;
        }
    }

    updateCalendarDayObjProperty (year, month, day, property, value, cb, returnNewData) {
        const calendarList = this.state.calendarList;
        const currMonthCalendarIndex = this.state.monthTitleList.findIndex((item) => {
            return ('' + item.year) === ('' + year) && ('' + item.month) === ('' + month);
        });
        const currMonthCalendar = calendarList[currMonthCalendarIndex];

        for (let i = 0; i < currMonthCalendar.length; i++) {
            const week = currMonthCalendar[i];
            const dayObj = week.find((item) => {
                return item.fullDate && ('' + day) === ('' + item.fullDate.day);
            });

            if (dayObj) {
                dayObj[property] = value;
                break;
            }
        }

        if (returnNewData) {
            return calendarList;
        }
        else {
            this.setState({
                calendarList: calendarList
            }, () => {
                if (cb) { cb(); }
            });
        }
    }

    getCalendarDayObjProperty (year, month, day, property) {
        const calendarList = this.state.calendarList;
        const currMonthCalendarIndex = this.state.monthTitleList.findIndex((item) => {
            return ('' + item.year) === ('' + year) && ('' + item.month) === ('' + month);
        });
        const currMonthCalendar = calendarList[currMonthCalendarIndex];

        for (let i = 0; i < currMonthCalendar.length; i++) {
            const week = currMonthCalendar[i];
            const dayObj = week.find((item) => {
                return item.fullDate && ('' + day) === ('' + item.fullDate.day);
            });

            if (dayObj) {
                return dayObj[property];
            }
        }
    }

    handleSigninCardClick () {
        const hasCard = this.state.signinCardCount > 0;

        if (hasCard) {
            Toast.info('点击日历中未签日期进行补签');
        }
        else {
            this.alertBuySigninCardModal();
        }
    }

    alertBuySigninCardModal () {
        const host = config.HOST_MONEY;
        const url = `${host}/card/info?card=sign_card&model=`;
        Modal.alert('', '你的补签卡不够哦，请先购买补签卡', [
            { text: '取消' },
            { text: '购买', onPress: () => { utils.navigate(url, true); } }
        ]);
    }

    handleCarouselChange (current) {
        this.setState({ activeSlideIndex: current });
        const currYear = this.state.monthTitleList[current].year;
        const currMonth = this.state.monthTitleList[current].month;
        this.getMonthSignRecord(currYear, currMonth);

        // 解决antd-mobile 走马灯 item高度不一致时，高度较大的显示不完整的bug
        Array.from(document.querySelectorAll('.calendar .slider-slide')).forEach((slide, index) => {
            if (index === current) {
                slide.classList.add('active');
            }
            else {
                slide.classList.remove('active');
            }
        });
    }

    render () {
        return (
            <div className="signinCalendar">
                <div className="calendar">
                    <div className="title">签到日历</div>
                    <div className="row handleBar">
                        <div
                            className={`signinCard ${this.state.signinCardCount > 0 ? 'hasCard' : ''}`}
                            onClick={() => { this.handleSigninCardClick(); }}
                        >
                            {this.state.signinCardCount > 0 ? '' : '补签卡'}
                            <Badge text={this.state.signinCardCount} />
                        </div>
                        {this.renderMonthTitle()}
                        <span className="todayJump" onClick={() => { this.handleTodayJumpClick(); }}></span>
                    </div>
                    <div className="row">
                        <Carousel
                            dots={false}
                            swipeSpeed={5}
                            selectedIndex={this.state.activeSlideIndex}
                            afterChange={(current) => { this.handleCarouselChange(current); }}
                        >
                            {this.renderCalendarPanel()}
                        </Carousel>
                    </div>
                    <div className="row">
                        <div className="good">
                            <span className="icon">宜</span>
                            {this.state.constellation.bad_good.good.join(' ')}
                        </div>
                        <div className="bad">
                            <span className="icon">忌</span>
                            {this.state.constellation.bad_good.bad.join(' ')}
                        </div>
                    </div>
                </div>
                {this.renderConstellation()}
                {this.renderSigninCardPop()}
            </div>
        );
    }
}
export default SigninCalendar;
